package cn.edu.njtc.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * MD5加密工具类
 */
public class MD5Utils {

    /**
     * 对字符串进行MD5加密（32位小写）
     * @param input 原始字符串
     * @return MD5加密后的字符串
     */
    public static String md5(String input) {
        if (input == null) {
            return null;
        }

        try {
            // 创建MessageDigest实例，指定MD5算法
            MessageDigest md = MessageDigest.getInstance("MD5");

            // 将输入字符串转换为字节数组并计算哈希值
            byte[] hash = md.digest(input.getBytes());

            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }

            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            // MD5算法应该总是可用，所以这里理论上不会发生
            throw new RuntimeException("MD5 algorithm not found", e);
        }
    }

    /**
     * 对字符串进行MD5加密（32位大写）
     * @param input 原始字符串
     * @return MD5加密后的字符串（大写）
     */
    public static String md5Upper(String input) {
        String lower = md5(input);
        return lower != null ? lower.toUpperCase() : null;
    }

    /**
     * 对字符串进行MD5加密（加盐）
     * @param input 原始字符串
     * @param salt 盐值
     * @return 加盐后的MD5加密字符串
     */
    public static String md5WithSalt(String input, String salt) {
        if (input == null) {
            return null;
        }
        if (salt == null) {
            salt = "";
        }
        return md5(input + salt);
    }

    /**
     * 验证原始字符串与MD5加密字符串是否匹配
     * @param input 原始字符串
     * @param md5Str MD5加密字符串
     * @return 是否匹配
     */
    public static boolean verify(String input, String md5Str) {
        if (input == null || md5Str == null) {
            return false;
        }
        return md5(input).equalsIgnoreCase(md5Str);
    }

    /**
     * 验证原始字符串与加盐MD5加密字符串是否匹配
     * @param input 原始字符串
     * @param salt 盐值
     * @param md5Str MD5加密字符串
     * @return 是否匹配
     */
    public static boolean verifyWithSalt(String input, String salt, String md5Str) {
        if (input == null || md5Str == null) {
            return false;
        }
        if (salt == null) {
            salt = "";
        }
        return md5(input + salt).equalsIgnoreCase(md5Str);
    }

    // 测试
    public static void main(String[] args) {
        String original = "HelloWorld123";

        System.out.println("MD5加密（小写）: " + md5(original));
        System.out.println("MD5加密（大写）: " + md5Upper(original));

        String salt = "RandomSalt";
        String saltedMd5 = md5WithSalt(original, salt);
        System.out.println("加盐MD5加密: " + saltedMd5);

        System.out.println("验证MD5: " + verify(original, md5(original)));
        System.out.println("验证加盐MD5: " + verifyWithSalt(original, salt, saltedMd5));
    }
}